package com.xiyu.service.framework.postOffice.service;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import com.xiyu.service.dal.websocket.downloadMailHeader.message.DownloadMailHeaderReceiverMessage;
import com.xiyu.service.dal.websocket.receiveMail.message.ReceiveMailReceiveMessage;
import com.xiyu.service.enums.common.UserTypeEnum;
import com.xiyu.service.enums.mailbox.folder.MailboxFolderClassEnum;
import com.xiyu.service.enums.mailbox.folder.MailboxFolderTypeEnum;
import com.xiyu.service.enums.mailbox.mail.MailboxMailResourceTypeEnum;
import com.xiyu.service.enums.mailbox.mail.MailboxMailStatusEnum;
import com.xiyu.service.enums.mailbox.mail.MailboxMailTypeEnum;
import com.xiyu.service.enums.mailbox.protocol.MailboxProtocolEnum;
import com.xiyu.service.framework.mail.service.BatchSendMailService;
import com.xiyu.service.framework.exception.ServiceException;
import com.xiyu.service.framework.file.core.utils.FileTypeUtils;
import com.xiyu.service.framework.postOffice.protocol.ImapProtocol;
import com.xiyu.service.framework.postOffice.protocol.PopProtocol;
import com.xiyu.service.framework.postOffice.protocol.ReceiveProtocol;
import com.xiyu.service.framework.postOffice.protocol.SmtpProtocol;
import com.xiyu.service.framework.postOffice.sync.SyncDownloadMailHeader;
import com.xiyu.service.framework.websocket.core.sender.WebSocketMessageSender;
import com.xiyu.service.model.mailbox.account.MailboxAccount;
import com.xiyu.service.model.mailbox.folder.MailboxFolder;
import com.xiyu.service.model.mailbox.folder.MailboxFolderDraft;
import com.xiyu.service.model.mailbox.folder.MailboxFolderNameMapping;
import com.xiyu.service.model.mailbox.label.MailboxLabel;
import com.xiyu.service.model.mailbox.mail.*;
import com.xiyu.service.repository.mailbox.account.MailboxAccountRepository;
import com.xiyu.service.repository.mailbox.folder.MailboxFolderNameMappingRepository;
import com.xiyu.service.repository.mailbox.folder.MailboxFolderRepository;
import com.xiyu.service.repository.mailbox.label.MailboxLabelRepository;
import com.xiyu.service.repository.mailbox.mail.MailboxMailErrorLogRepository;
import com.xiyu.service.repository.mailbox.mail.MailboxMailResourceRepository;
import com.xiyu.service.repository.mailbox.mail.MailboxMailRepository;
import com.xiyu.service.service.infra.file.FileService;
import com.xiyu.service.service.mailbox.MailboxMailErrorLogService;
import jakarta.activation.DataHandler;
import jakarta.activation.DataSource;
import jakarta.mail.*;
import jakarta.mail.internet.*;
import jakarta.mail.util.ByteArrayDataSource;
import jakarta.mail.util.SharedByteArrayInputStream;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.babyfish.jimmer.ImmutableObjects;
import org.babyfish.jimmer.sql.ast.mutation.SaveMode;
import org.babyfish.jimmer.sql.ast.tuple.Tuple3;
import org.eclipse.angus.mail.imap.IMAPFolder;
import org.jetbrains.annotations.NotNull;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import jakarta.annotation.Resource;
import java.io.*;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

import static com.xiyu.service.errorCode.mailbox.MailErrorCode.*;
import static com.xiyu.service.errorCode.mailbox.PostOfficeErrorCode.*;
import static com.xiyu.service.framework.exception.util.ServiceExceptionUtil.exception;
import static com.xiyu.service.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;

@Component
@Scope("prototype")
@Slf4j
public class PostOfficeService {

    private ReceiveProtocol receiveProtocol;

    private MailboxAccount mailboxAccount;

    @Resource
    private MailboxAccountRepository mailboxAccountRepository;

    @Resource
    private MailboxFolderRepository mailboxFolderRepository;

    @Resource
    private MailboxFolderNameMappingRepository mailboxFolderNameMappingRepository;

    @Resource
    private MailboxMailRepository mailboxMailRepository;

    @Resource
    private MailboxMailResourceRepository mailboxMailResourceRepository;

    @Resource
    MailboxMailErrorLogRepository mailboxMailErrorLogRepository;

    @Resource
    private MailboxLabelRepository mailboxLabelRepository;

    @Resource
    private SyncDownloadMailHeader syncDownloadMailHeader;

    @Resource
    private WebSocketMessageSender webSocketMessageSender;

    @Resource
    private MailboxMailErrorLogService mailboxMailErrorLogService;

    @Resource
    private FileService fileService;

    @Resource
    BatchSendMailService batchSendMailService;

    @Resource
    SmtpProtocol smtpProtocol;


    private void getInstance(MailboxAccount account) {
        try {
            if (account.mailboxProtocolType().equals(MailboxProtocolEnum.IMAP.getValue())) {
                receiveProtocol = new ImapProtocol(account);
            } else {
                receiveProtocol = new PopProtocol(account);
            }
            mailboxAccount = account;
        }catch (ServiceException e) {
            // 将自定义异常包装成 BeanCreationException
            throw new BeanCreationException("Failed to create bean due to protocol", e);
        }
    }
    
    public PostOfficeService(MailboxAccount account){
        getInstance(account);
    }

    public void close(){
        receiveProtocol.close();
    }

    public void testGetMessage(){
        receiveProtocol.testGetMessage();
    }


    /**
     * 创建邮箱账号
     */
    public void createAccount(){
        createRootFolder();
        // 同步文件夹
        syncFolders();
    }

    /**
     * 创建邮箱的根文件夹
     */
    private void createRootFolder(){
        // 新建根文件夹
        Folder rootFolder = receiveProtocol.getRootFolder();
        MailboxFolder rootMailFolder = MailboxFolderDraft.$.produce(draft -> draft.setAccountId(mailboxAccount.id())
                .setName(mailboxAccount.showName())
                .setFolderType(MailboxFolderTypeEnum.ACCOUNT.getValue()).setFolderClass(MailboxFolderClassEnum.ACCOUNT.getValue())
                .setPostOfficeName(receiveProtocol.getFolderName(rootFolder)));
        mailboxFolderRepository.insert(rootMailFolder);
    }

    /**
     * 根据邮局文件夹判断是否是内置文件夹，如果是返回系统文件夹名，如果不是返回空
     * @param folder 邮局文件夹
     * @return 系统文件夹名称
     */
    private String getInternalFolderName(Folder folder){
        Optional<MailboxFolderNameMapping> optionalFolderMapping = mailboxFolderNameMappingRepository.findByPostOfficeFolderName(receiveProtocol.getFolderName(folder));
        if(optionalFolderMapping.isPresent()){
            return optionalFolderMapping.get().mailboxFolderName();
        }else{
            String[] postOfficeFolderAttributes = receiveProtocol.getFolderAttributes(folder);
            if(Arrays.stream(postOfficeFolderAttributes).anyMatch(attribute ->attribute.contains("Drafts")))
                return "draft";
            if(Arrays.stream(postOfficeFolderAttributes).anyMatch(attribute ->attribute.contains("Sent")))
                return "send";
            if(Arrays.stream(postOfficeFolderAttributes).anyMatch(attribute ->attribute.contains("Trash")))
                return "delete";
            if(Arrays.stream(postOfficeFolderAttributes).anyMatch(attribute ->attribute.contains("Junk")))
                return "junk";
        }
        return "";
    }

    /**
     * 同步邮局文件夹
     * @param postOfficeFolders 邮局文件夹
     */
    private void syncPostOfficeFolders(List<Folder> postOfficeFolders){

        List<MailboxFolder> folders = convertPostOfficeFolder(postOfficeFolders);
        foldersSort(folders);
        for(MailboxFolder folder : folders){
            MailboxFolder newFolder = mailboxFolderRepository.save(folder, SaveMode.NON_IDEMPOTENT_UPSERT).getModifiedEntity();
            mailboxFolderRepository.updateSort(newFolder.id(), newFolder.id());
        }

    }

    /**
     * 同步账号的所有文件夹
     */
    public void syncFolders(){
        // 先将MailboxFolderTypeEnum.EDIT类型的文件夹的post_office_name字段全部置空 更新后还未空的则删除
        mailboxFolderRepository.updatePostOfficeNameEmpty(mailboxAccount.id(), MailboxFolderTypeEnum.EDIT.getValue());
        List<Folder> postOfficeFolders = receiveProtocol.getAllFolder();
        syncPostOfficeFolders(postOfficeFolders);
        syncInternalFolder();
        mailboxFolderRepository.deletePostOfficeNameEmpty(mailboxAccount.id(), MailboxFolderTypeEnum.EDIT.getValue());
    }

    /**
     * 将邮局文件夹类转换成系统文件夹类
     * @param postOfficeFolders 邮局文件夹类
     * @return 系统文件夹类
     */
    private List<MailboxFolder> convertPostOfficeFolder(List<Folder> postOfficeFolders){
        Optional<MailboxFolder> rootFolder = mailboxFolderRepository.findRootFolder(mailboxAccount.id());
        if (rootFolder.isEmpty()){
            throw exception(MAILBOX_ROOT_FOLDER_NOT_EXIST);
        }
        long parentId = rootFolder.get().id();
        List<MailboxFolder> folders = new ArrayList<>();
        for(Folder postOfficeFolder : postOfficeFolders){
            String postOfficeFolderName = receiveProtocol.getFolderName(postOfficeFolder);
            if(postOfficeFolderName.length() > 255){
                throw exception(POST_OFFICE_FOLDER_NAME_TO_LONG);
            }

            String[] folderAttributes = receiveProtocol.getFolderAttributes(postOfficeFolder);
            if(Arrays.stream(folderAttributes).anyMatch(attribute -> attribute.contains("NoSelect"))){
                continue;
            }
            Integer folderType = MailboxFolderTypeEnum.EDIT.getValue();
            Integer folderClass = MailboxFolderClassEnum.OTHER.getValue();

            // 根据内置文件夹映射判断是否是内置文件夹
            String folderName = getInternalFolderName(postOfficeFolder);
            if(!folderName.isEmpty()){
                folderType = MailboxFolderTypeEnum.INTERNAL.getValue();
                switch (folderName) {
                    case "receive" -> folderClass = MailboxFolderClassEnum.RECEIVE.getValue();
                    case "draft" -> folderClass = MailboxFolderClassEnum.DRAFT.getValue();
                    case "send" -> folderClass = MailboxFolderClassEnum.SEND.getValue();
                    case "delete" -> folderClass = MailboxFolderClassEnum.DELETED.getValue();
                    case "junk" -> folderClass = MailboxFolderClassEnum.JUNK.getValue();
                }

            }else{
                // 找到最后一个 '/' 的位置
                int lastSlashIndex = postOfficeFolderName.lastIndexOf('/');
                if(lastSlashIndex > -1){
                    folderName = postOfficeFolderName.substring(lastSlashIndex + 1);
                    if (postOfficeFolderName.lastIndexOf('/') > -1){
                        String parentUrlFolderName = postOfficeFolderName.substring(0, postOfficeFolderName.lastIndexOf('/'));
                        Optional<MailboxFolder> optionalParentFolder = mailboxFolderRepository.findByAccountIdAndPostOfficeName(mailboxAccount.id(), parentUrlFolderName);
                        if(optionalParentFolder.isPresent())
                            parentId = optionalParentFolder.get().id();
                    }
                }else{
                    folderName = postOfficeFolderName;
                }
            }

            Optional<MailboxFolder> oldFolders = mailboxFolderRepository.findFirstByParentIdAndName(parentId, folderName);
            String finalFolderName = folderName;
            int finalFolderClass = folderClass;
            Integer finalFolderType = folderType;
            Long finalParentId = parentId;
            MailboxFolder mailboxFolder;
            if(oldFolders.isEmpty())
            {
                mailboxFolder = MailboxFolderDraft.$.produce(draft ->
                        draft.setAccountId(mailboxAccount.id()).setName(finalFolderName).setParentId(finalParentId)
                        .setFolderType(finalFolderType).setFolderClass(finalFolderClass)
                        .setPostOfficeName(postOfficeFolderName));
            }else{
                mailboxFolder = MailboxFolderDraft.$.produce(oldFolders.get(), draft ->
                        draft.setAccountId(mailboxAccount.id()).setName(finalFolderName).setParentId(finalParentId)
                        .setFolderType(finalFolderType).setFolderClass(finalFolderClass)
                        .setPostOfficeName(postOfficeFolderName));
            }

            folders.add(mailboxFolder);
        }
        return folders;
    }

    /**
     * 对邮箱系统文件夹进行排序 内置文件夹在前，其他文件夹在后
     * @param folders 邮箱系统文件夹
     */
    private void foldersSort(List<MailboxFolder> folders){
        String[] internalFolderNameArray = {"receive", "draft", "send", "delete", "junk"};
        List<String> internalFolderNames = Arrays.asList(internalFolderNameArray);
        folders.sort((s1, s2) -> {
            String s1Name = s1.name();
            String s2Name = s2.name();
            boolean s1IsInternal = internalFolderNames.contains(s1Name);
            boolean s2IsInternal = internalFolderNames.contains(s2Name);

            if (s1IsInternal && !s2IsInternal) {
                return -1; // s1 排在前面
            }
            if (!s1IsInternal && s2IsInternal) {
                return 1; // s2 排在前面
            }
            if (s1IsInternal) {
                return Integer.compare(internalFolderNames.indexOf(s1Name), internalFolderNames.indexOf(s2Name));
            }
            return 0; // 保持原顺序
        });
    }

    private void insertLabelFolder(MailboxFolder rootLabelFolder){
        List<MailboxLabel> labelList = mailboxLabelRepository.findByOwnerId(getLoginUserId());
        for(MailboxLabel label : labelList){
            MailboxFolder labelFolder = MailboxFolderDraft.$.produce(draft -> draft.setName(label.name()).setFolderType(MailboxFolderTypeEnum.LABEL.getValue())
                    .setColor(label.color())
                    .setParentId(rootLabelFolder.id()).setAccountId(rootLabelFolder.accountId())
                    .setFolderClass(MailboxFolderClassEnum.LABEL.getValue()));
            labelFolder = mailboxFolderRepository.insert(labelFolder);
            mailboxFolderRepository.updateSort(labelFolder.id(), labelFolder.id());
        }
    }

    /**
     * 同步内置文件夹，不存在就插入
     */
    private void syncInternalFolder(){
        Map<String, Integer> internalFolderMap = new HashMap<>(6){{
            put("receive", MailboxFolderClassEnum.RECEIVE.getValue());
            put("draft", MailboxFolderClassEnum.DRAFT.getValue());
            put("send", MailboxFolderClassEnum.SEND.getValue());
            put("delete", MailboxFolderClassEnum.DELETED.getValue());
            put("junk", MailboxFolderClassEnum.JUNK.getValue());
            put("label", MailboxFolderClassEnum.LABEL.getValue());
        }};
        Optional<MailboxFolder> rootFolder = mailboxFolderRepository.findRootFolder(mailboxAccount.id());
        if (rootFolder.isEmpty()){
            throw exception(MAILBOX_ROOT_FOLDER_NOT_EXIST);
        }
        for (Map.Entry<String, Integer> entry : internalFolderMap.entrySet()) {
            Integer folderType = Objects.equals(entry.getValue(), MailboxFolderClassEnum.LABEL.getValue()) ? MailboxFolderTypeEnum.LABEL.getValue():MailboxFolderTypeEnum.INTERNAL.getValue();
            List<MailboxFolder> internalFolders = mailboxFolderRepository.findByAccountIdAndFolderTypeAndName(mailboxAccount.id(), folderType, entry.getKey());
            if(internalFolders.size() == 0){
                MailboxFolder newFolder = mailboxFolderRepository.insert(MailboxFolderDraft.$.produce(draft -> draft.setAccountId(mailboxAccount.id()).setName(entry.getKey()).setParentId(rootFolder.get().id())
                        .setFolderType(folderType)
                        .setFolderClass(entry.getValue())));
                mailboxFolderRepository.updateSort(newFolder.id(), newFolder.id());
                if(Objects.equals(entry.getValue(), MailboxFolderClassEnum.LABEL.getValue())){
                    insertLabelFolder(newFolder);
                }
            }
        }
    }

    /**
     * 创建文件夹
     * @param newFolder 新的系统邮箱文件夹
     * @return 邮局文件夹的文件路径
     */
    public String createFolder(MailboxFolder newFolder){
        MailboxFolder parentFolder = getParentFolder(newFolder.parentId());
        return receiveProtocol.createFolder(parentFolder.postOfficeName(), newFolder.name());
    }

    /**
     * 重命名文件夹
     * @param folder 要重命名的系统邮箱文件夹
     * @return 邮局文件夹的文件路径
     */
    public String renameFolder(MailboxFolder folder){
        MailboxFolder parentFolder = getParentFolder(folder.parentId());
        return receiveProtocol.renameFolder(parentFolder.postOfficeName(), folder.postOfficeName(), folder.name());
    }

    /**
     * 删除文件夹
     * @param deleteFolder 要删除的系统邮箱文件夹
     */
    public void deleteFolder(MailboxFolder deleteFolder){
        receiveProtocol.deleteFolder(deleteFolder.postOfficeName());
    }

    /**
     * 获取父文件夹
     * @param parentId 父文件夹ID
     * @return 父文件夹
     */
    private MailboxFolder getParentFolder(Long parentId){
        Optional<MailboxFolder> optionalParentFolder = mailboxFolderRepository.findById(parentId);
        if(optionalParentFolder.isEmpty()){
            throw exception(POST_OFFICE_PARENT_FOLDER_NOT_EXISTS);
        }
        return optionalParentFolder.get();
    }

    /**
     * 批量设置邮局标记
     * @param mailList 需要设置的邮件列表
     * @param flag 标记
     * @param isTrue true 打上标记 false 去掉标记
     */
    private void batchSetMailFlag(List<MailboxMail> mailList, Flags.Flag flag, boolean isTrue){
        HashMap<Long, List<MailboxMail>> folderMailMap = new HashMap<>();
        for(MailboxMail mail : mailList){
            if(folderMailMap.containsKey(mail.folderId())){
                folderMailMap.get(mail.folderId()).add(mail);
            }else{
                List<MailboxMail> mails = new ArrayList<>();
                mails.add(mail);
                folderMailMap.put(mail.folderId(), mails);
            }
        }
        for(Map.Entry<Long, List<MailboxMail>> entry : folderMailMap.entrySet()){
            MailboxFolder folder = mailboxFolderRepository.findNullable(entry.getKey());
            Folder postOfficeFolder = getPostOfficeFolder(folder);
            receiveProtocol.openFolder(postOfficeFolder, Folder.READ_WRITE);
            String[] uniqueIds = entry.getValue().stream().map(MailboxMail::uid).collect(Collectors.toList()).toArray(String[]::new);
            Message[] messages = receiveProtocol.getMessagesByUid(postOfficeFolder, uniqueIds);
            Flags flags = new Flags(flag);
            receiveProtocol.setMessagesFlag(postOfficeFolder, messages, flags, isTrue);
            receiveProtocol.closeFolder(postOfficeFolder, true);
        }
    }

    /**
     * 标记邮件是否已读
     * @param mailList 邮件列表
     * @param isRead 是否已读 true:已读 false:未读
     */
    public void setMailRead(List<MailboxMail> mailList, boolean isRead){
        batchSetMailFlag(mailList, Flags.Flag.SEEN, isRead);

    }

    /**
     * 标记邮件是否置顶
     * @param mailList 邮件列表
     * @param isTop 是否置顶 true:置顶 false:取消置顶
     */
    public void setMailTop(List<MailboxMail> mailList, boolean isTop){
        batchSetMailFlag(mailList, Flags.Flag.FLAGGED, isTop);
    }

    /**
     * 移动文件夹
     * @param sourceFolder 移出文件夹
     * @param targetFolder 移入文件夹
     * @param mail 移动的邮件
     * @return 移动后的邮件的新UID
     */
    public String moveMailFolder(MailboxFolder sourceFolder, MailboxFolder targetFolder, MailboxMail mail){
        Folder targetPostOfficeFolder = getPostOfficeFolder(targetFolder);
        receiveProtocol.openFolder(targetPostOfficeFolder, Folder.READ_WRITE);

        Folder sourcePostOfficeFolder = getPostOfficeFolder(sourceFolder);
        receiveProtocol.openFolder(sourcePostOfficeFolder, Folder.READ_WRITE);
        String[] uniqueIds = {mail.uid()};
        Message[] messages = receiveProtocol.getMessagesByUid(sourcePostOfficeFolder, uniqueIds);
        long[] targetUid = receiveProtocol.moveMessages(sourcePostOfficeFolder, targetPostOfficeFolder, messages);
        receiveProtocol.closeFolder(sourcePostOfficeFolder, true);
        receiveProtocol.closeFolder(targetPostOfficeFolder, true);
        return String.valueOf(targetUid[0]);
    }

    /**
     * 删除邮件
     * @param folder 邮件所在文件夹
     * @param mail 要删除的邮件
     */
    public void deleteMail(MailboxFolder folder, MailboxMail mail){
        Folder postOfficeFolder = getPostOfficeFolder(folder);
        receiveProtocol.openFolder(postOfficeFolder, Folder.READ_WRITE);
        String[] uniqueIds = {mail.uid()};
        Message[] messages = receiveProtocol.getMessagesByUid(postOfficeFolder, uniqueIds);
        receiveProtocol.deleteMessages(postOfficeFolder, messages);
        receiveProtocol.closeFolder(postOfficeFolder, true);
    }

    /**
     * 根据系统邮箱文件夹获取邮局文件夹
     * @param folder 系统邮箱文件夹
     * @return 邮局文件夹
     */
    private Folder getPostOfficeFolder(MailboxFolder folder){
        return receiveProtocol.getFolderByName(folder.postOfficeName());
    }

    /**
     * 定时收取邮局正文
     */
    public void receiveAccountMailContentJob(){
        syncFolders();
        List<MailboxFolder> folders = mailboxFolderRepository.findSyncFolder(mailboxAccount.id());
        for(MailboxFolder folder : folders){
            receiveFolderMailContent(folder);
        }
    }

    /**
     * 按文件夹收取邮件正文
     * @param folder 系统邮箱文件夹
     */
    private void receiveFolderMailContent(MailboxFolder folder){
        try {
            List<MailboxMail> folderMails = mailboxMailRepository.getUnReceiveContentMailByFolderId(folder.id());
            Folder postOfficeFolder = getPostOfficeFolder(folder);
            receiveProtocol.openFolder(postOfficeFolder, Folder.READ_ONLY);
            int count = 0;
            for (MailboxMail mail : folderMails) {
                try {
                    String[] uniqueIds = {mail.uid()};
                    Message[] messages = receiveProtocol.getMessagesByUid(postOfficeFolder, uniqueIds);
                    String content = getMailContentByMessage(mail.id(), messages[0]);
                    String searchContent = getMailSearchContent(mail, content);
                    List<MailboxMailResource> resources = mailboxMailResourceRepository.findByMailIdAndResourceType(mail.id(), MailboxMailResourceTypeEnum.ATTACHMENT.getValue());
                    mailboxMailRepository.updateMailContent(mail.id(), content, searchContent, !resources.isEmpty());
                    count++;
                    // 长时间收取会超时，每收取1000重新启动
                    if (count > 1000)
                        break;
                }catch (Exception e){
                    mailboxMailErrorLogService.saveMailErrorInfo(mailboxAccount.id(), folder.id(), mail.id(), mail.uid(), e);
                }
            }
            receiveProtocol.closeFolder(postOfficeFolder, false);
        }catch (Exception e){
            mailboxMailErrorLogService.saveMailErrorInfo(mailboxAccount.id(), folder.id(), 0L, "", e);
        }
    }

    public String getMailSearchContent(MailboxMail mail, String content){
        StringBuilder searchContent;
        // 从邮件正文中提取内容
        Document doc = Jsoup.parse(content);
        Element body = doc.body();
        searchContent = new StringBuilder(body.text());
        String senderName = "", senderAddress = "";
        if(ImmutableObjects.isLoaded(mail, MailboxMailProps.SENDER_NAME)){
            senderName = mail.senderName();
        }
        if(ImmutableObjects.isLoaded(mail, MailboxMailProps.SENDER_ADDRESS)){
            senderAddress = mail.senderAddress();
        }
        searchContent.append(" ").append(senderName).append(" ").append(senderAddress);
        for(MailboxMailFrom from : mail.froms()){
            searchContent.append(" ").append(from.address()).append(" ").append(from.name());
        }
        for(MailboxMailReceiver receiver : mail.receivers()){
            searchContent.append(" ").append(receiver.address()).append(" ").append(receiver.name());
        }
        for(MailboxMailReceiver carbonReceiver : mail.carbonReceivers()){
            searchContent.append(" ").append(carbonReceiver.address()).append(" ").append(carbonReceiver.name());
        }
        for(MailboxMailResource resource : mail.resources()){
            searchContent.append(" ").append(resource.fileName());
        }

        return searchContent.toString();
    }

    /**
     * 定时收取邮件文件头
     */
    public void receiveAccountMailJob(){
        syncFolders();
        List<MailboxFolder> folders = mailboxFolderRepository.findSyncFolder(mailboxAccount.id());
        for(MailboxFolder folder : folders){
            receiveFolderMail(folder, true);
        }
        mailboxAccountRepository.updateLastReceiveTime(mailboxAccount.id(), LocalDateTime.now());
    }

    /**
     * 收取账号的邮件头
     */
    public void receiveAccountMail(){
        receiveMailSendMessage("检查文件夹的状态", "check_folder", mailboxAccount.showName());
        syncFolders();
        List<MailboxFolder> folders = mailboxFolderRepository.findSyncFolder(mailboxAccount.id());
        for(MailboxFolder folder : folders){
            receiveMailSendMessage(folder.name(), "folder_begin", mailboxAccount.showName());
            receiveFolderMail(folder, false);
            receiveMailSendMessage(folder.name() , "folder_done", mailboxAccount.showName());
        }
        mailboxAccountRepository.updateLastReceiveTime(mailboxAccount.id(), LocalDateTime.now());
    }

    /**
     * 按文件夹收取邮件
     * @param folder 系统邮箱文件夹
     * @param isReceiveAll 是否接收所有邮件 true 会对比文件夹的邮件总数量 如果不一致会倒序收取邮件直到数量相同 false 只收取最新邮件 不判断总数量
     */
    public void receiveFolderMail(MailboxFolder folder, boolean isReceiveAll){

        Integer folderMailCount = folder.mailCount();
        Integer folderReadMailCount = folder.readMailCount();
        Integer folderTopMailCount = folder.topMailCount();

        Folder postOfficeFolder = getPostOfficeFolder(folder);
        receiveProtocol.openFolder(postOfficeFolder, Folder.READ_ONLY);
        int postOfficeMailCount = receiveProtocol.getFolderMailCount(postOfficeFolder);

        // 接收最新邮件
        Tuple3<Long, Long, Long> folderInfo1 = receiveRecentFolderMail(postOfficeFolder, folder, postOfficeMailCount);
        if(folderInfo1 != null){
            folderMailCount = folderInfo1.component1().intValue();
            folderReadMailCount = folderInfo1.component2().intValue();
            folderTopMailCount = folderInfo1.component3().intValue();
            // 更新文件夹的邮件数量、已读数量、置顶数量
            mailboxFolderRepository.updateCount(folder.id(), folderMailCount, folderReadMailCount, folderTopMailCount);
        }

        if(!isReceiveAll)
            return;

        // 未读邮件数量
        int postOfficeUnreadMailCount = receiveProtocol.getFolderUnreadMailCount(postOfficeFolder);
        int postOfficeReadMailCount = postOfficeMailCount - postOfficeUnreadMailCount;
        // 置顶邮件数量
        int topMailCount = receiveProtocol.getFolderTopMailCount(postOfficeFolder);
        if(folderMailCount.equals(postOfficeMailCount) && folderReadMailCount.equals(postOfficeReadMailCount) && folderTopMailCount.equals(topMailCount)){
            receiveProtocol.closeFolder(postOfficeFolder, false);
            return;
        }

        // 接收未读邮件
        if((folderMailCount - folderReadMailCount) != (postOfficeUnreadMailCount)){
            Tuple3<Long, Long, Long> folderInfo3 = receiveUnreadFolderMail(postOfficeFolder, folder);
            if(folderInfo3 != null){
                folderMailCount = folderInfo3.component1().intValue();
                folderReadMailCount = folderInfo3.component2().intValue();
                folderTopMailCount = folderInfo3.component3().intValue();
            }
        }
        // 如果邮件数量和系统对不上，下载全部直到相等
        if(!folderMailCount.equals(postOfficeMailCount)){
            Tuple3<Long, Long, Long> folderInfo3 = receiveAllFolderMail(postOfficeFolder, folder, postOfficeMailCount);
            if(folderInfo3 != null){
                folderMailCount = folderInfo3.component1().intValue();
                folderReadMailCount = folderInfo3.component2().intValue();
                folderTopMailCount = folderInfo3.component3().intValue();
            }
        }
        // 接收置顶邮件
        if(!folderTopMailCount.equals(topMailCount)){
            LinkedHashMap<String, Message> topMessageMap = receiveProtocol.getFolderTopMessages(postOfficeFolder);
            for (Map.Entry<String, Message> entry : topMessageMap.entrySet()) {
                downloadOneMailHeader(folder, entry.getValue(), entry.getKey());
            }
            folderTopMailCount = mailboxMailRepository.findTopMailCount(folder.id()).intValue();
        }
        receiveProtocol.closeFolder(postOfficeFolder, false);
        // 更新文件夹的邮件数量、已读数量、置顶数量
        mailboxFolderRepository.updateCount(folder.id(), folderMailCount, folderReadMailCount, folderTopMailCount);
    }

    /**
     * 收取文件夹未读邮件
     * @param postOfficeFolder 邮局文件夹
     * @param folder 系统邮箱文件夹
     * @return 收取后文件夹的邮件总数量、已读邮件数量、置顶邮件数量
     */
    private Tuple3<Long, Long, Long> receiveUnreadFolderMail(Folder postOfficeFolder, MailboxFolder folder){
        boolean isCreate = false;
        Tuple3< Long, Long, Long> folderInfo = null;
        LinkedHashMap<String, Message> unreadMessageMap = receiveProtocol.getFolderUnreadMessages(postOfficeFolder);
        if(unreadMessageMap == null)
            return null;
        for (Map.Entry<String, Message> entry : unreadMessageMap.entrySet()) {
            if(downloadOneMailHeader(folder, entry.getValue(), entry.getKey())){
                isCreate = true;
            }
        }
        if(isCreate){
            folderInfo = calcFolderMailCountInfo(folder.id());
        }
        return folderInfo;
    }

    /**
     * 收取文件夹所有邮件
     * @param postOfficeFolder 邮局文件夹
     * @param folder 系统邮箱文件夹
     * @param postOfficeMailCount 邮局文件夹的邮件总数量
     * @return 收取后文件夹的邮件总数量、已读邮件数量、置顶邮件数量
     */
    private Tuple3<Long, Long, Long> receiveAllFolderMail(Folder postOfficeFolder, MailboxFolder folder, int postOfficeMailCount){
        int interval = 100;
        int currentEnd = postOfficeMailCount;

        while (true){
            Tuple3< Long, Long, Long> folderInfo = null;
            int currentBegin = Math.max(currentEnd - interval + 1, 1);
            boolean isCreate = false;
            LinkedHashMap<String, Message> messageMap = receiveProtocol.getFolderMessages(postOfficeFolder, currentBegin, currentEnd);
            for (Map.Entry<String, Message> entry : messageMap.entrySet()) {
                if(downloadOneMailHeader(folder, entry.getValue(), entry.getKey())){
                    isCreate = true;
                }
            }
            if(isCreate){
                folderInfo = calcFolderMailCountInfo(folder.id());
                if(folderInfo.get_1().intValue() == postOfficeMailCount){
                    return folderInfo;
                }
            }
            if(currentBegin <= 1){
                return folderInfo;
            }
            currentEnd = Math.max(currentEnd - interval, 1);
        }
    }

    /**
     * 收取文件夹最近邮件
     * @param postOfficeFolder 邮局文件夹
     * @param folder 系统邮箱文件夹
     * @param postOfficeMailCount 邮局文件夹的邮件总数量
     * @return 收取后文件夹的邮件总数量、已读邮件数量、置顶邮件数量
     */
    private Tuple3<Long, Long, Long> receiveRecentFolderMail(Folder postOfficeFolder, MailboxFolder folder, int postOfficeMailCount){
        int interval = 5;
        int currentEnd = postOfficeMailCount;
        boolean isCreate = false;
        boolean isExists = false;
        while (true){
            int currentBegin = Math.max(currentEnd - interval + 1, 1);
            LinkedHashMap<String, Message> messageMap = receiveProtocol.getFolderMessages(postOfficeFolder, currentBegin, currentEnd);
            for (Map.Entry<String, Message> entry : messageMap.entrySet()) {
                if(downloadOneMailHeader(folder, entry.getValue(), entry.getKey())){
                    isCreate = true;
                }else{
                    isExists = true;
                }
            }
            if(currentBegin <= 1 || isExists)
                break;
            currentEnd = Math.max(currentEnd - interval, 1);
        }
        if(isCreate){
            return calcFolderMailCountInfo(folder.id());
        }
        return null;
    }

    /**
     * 计算文件夹的邮件总数量、已读邮件数量、置顶邮件数量，并更新到文件夹对应字段
     * @param folderId 系统邮箱文件夹
     * @return 文件夹的邮件总数量、已读邮件数量、置顶邮件数量
     */
    private Tuple3< Long, Long, Long> calcFolderMailCountInfo(Long folderId){
        Tuple3< Long, Long, Long> mailGroupInfo = mailboxMailRepository.groupCountByFolderId(folderId);
        mailboxFolderRepository.updateCount(folderId, mailGroupInfo.component1().intValue(), mailGroupInfo.component2().intValue(), mailGroupInfo.component3().intValue());
        return mailGroupInfo;
    }

    public void downloadMailHeaderTask(int begin, int end, Runnable onComplete, Long folderId){
        Optional<MailboxFolder> optionalFolder = mailboxFolderRepository.findById(folderId);
        if(optionalFolder.isEmpty()){
            throw exception(POST_OFFICE_GET_FOLDER_ERROR);
        }
        Folder postOfficeFolder = getPostOfficeFolder(optionalFolder.get());
        receiveProtocol.openFolder(postOfficeFolder, Folder.READ_ONLY);
        int interval = 100;
        int currentBegin = begin;
        while(true){
            int currentEnd = Math.min(currentBegin + interval - 1, end);
            LinkedHashMap<String, Message> messageMap = receiveProtocol.getFolderMessages(postOfficeFolder, currentBegin, currentEnd);
            for (Map.Entry<String, Message> entry : messageMap.entrySet()) {
                downloadOneMailHeader(optionalFolder.get(), entry.getValue(), entry.getKey());
            }
            onComplete.run();
            if(currentEnd >= end)
                break;
            currentBegin = Math.min(currentBegin + interval, end);
        }
        receiveProtocol.closeFolder(postOfficeFolder, false);
    }

    /**
     * 下载账号的邮件头
     */
    public void downloadAccountMailHeader(){
        List<CompletableFuture<Void>> futureList = new ArrayList<>();
        downloadMailHeaderSendMessage("正在检查文件夹的状态", 0, 0, "check_folder");
        syncFolders();
        List<MailboxFolder> folders = mailboxFolderRepository.findSyncFolder(mailboxAccount.id());
        for(MailboxFolder folder : folders){
            futureList.addAll(downloadFolderMailHeader(folder));
        }
        // 等待所有外部任务完成并收集结果
        CompletableFuture<Void> allOf = CompletableFuture.allOf(futureList.toArray(new CompletableFuture[0]));
        // 阻塞主线程，等待所有任务完成
        allOf.join();
        for(MailboxFolder folder : folders){
            calcFolderMailCountInfo(folder.id());
        }
        downloadMailHeaderSendMessage("任务成功完成", 0, 0, "done");
    }

    /**
     * 下载文件夹下的邮件头
     * @param folder 系统邮箱文件夹
     * @return 异步任务对象
     */
    public List<CompletableFuture<Void>> downloadFolderMailHeader(MailboxFolder folder){
        List<CompletableFuture<Void>> futureList = new ArrayList<>();
        Folder postOfficeFolder = getPostOfficeFolder(folder);
        receiveProtocol.openFolder(postOfficeFolder, Folder.READ_ONLY);
        int messageCount = receiveProtocol.getFolderMailCount(postOfficeFolder);
        downloadMailHeaderSendMessage(folder.name(), 0, messageCount, "folder_begin");
        if(messageCount < 2000){
            int interval = 100;
            int currentBegin = 1;
            int downloadCount = 1;
            while(true){
                int currentEnd = Math.min(currentBegin + interval - 1, messageCount);
                LinkedHashMap<String, Message> messageMap = receiveProtocol.getFolderMessages(postOfficeFolder, currentBegin, currentEnd);
                for (Map.Entry<String, Message> entry : messageMap.entrySet()) {
                    downloadOneMailHeader(folder, entry.getValue(), entry.getKey());
                    downloadMailHeaderSendMessage(folder.name(), messageCount, downloadCount++, "receiving");
                }
                if(currentEnd >= messageCount)
                    break;
                currentBegin = Math.min(currentBegin + interval, messageCount);
            }
            downloadMailHeaderSendMessage(folder.name(), messageCount, messageCount, "folder_done");
        }else{
            AtomicInteger downloadCount = new AtomicInteger(0);
            Runnable onTaskComplete = () -> {
                downloadCount.addAndGet(100);
                downloadMailHeaderSendMessage(folder.name(), messageCount, downloadCount.get(), "receiving");
            };
            int treadCount = 5;
            int intervalCount = Math.floorDiv(messageCount, treadCount);
            int mod = Math.floorMod(messageCount, treadCount);
            int beginIndex = 1;
            for (int i = 0; i < treadCount; i++) {
                futureList.add(syncDownloadMailHeader.downloadMailHeaderTask(beginIndex, beginIndex + intervalCount - 1 + (treadCount - 1 == i ? mod : 0), onTaskComplete, folder.accountId(), folder.id())) ;
                beginIndex = beginIndex + intervalCount;
            }
        }
        receiveProtocol.closeFolder(postOfficeFolder, false);
        return futureList;
    }

    /**
     * 发送下载邮件头的websocket信息
     * @param message 信息内容
     * @param totalCount 文件夹的邮件总数量
     * @param downloadCount 已经下载的邮件总数量
     * @param status 当前状态
     */
    private void downloadMailHeaderSendMessage(String message, int totalCount, int downloadCount, String status){
        DownloadMailHeaderReceiverMessage toMessage = new DownloadMailHeaderReceiverMessage(message, status, totalCount, downloadCount);
        webSocketMessageSender.sendObject(UserTypeEnum.ADMIN.getValue(), getLoginUserId(),
                "download-mail-header", toMessage);
    }

    /**
     * 发送收取邮件的websocket信息
     * @param message 信息内容
     * @param status 当前状态
     * @param accountName 当前正在收取邮件的邮箱账号
     */
    private void receiveMailSendMessage(String message, String status, String accountName){
        ReceiveMailReceiveMessage toMessage = new ReceiveMailReceiveMessage(message, status, accountName);
        webSocketMessageSender.sendObject(UserTypeEnum.ADMIN.getValue(), getLoginUserId(),
                "receive-mail", toMessage);
    }

    /**
     * 更新邮件标记
     * @param mailId 邮件ID
     * @param message 邮件message
     */
    private void updateMailFlag(Long mailId, Message message){
        try {
            boolean isRead = message.getFlags().contains(Flags.Flag.SEEN);
            boolean isTop = message.getFlags().contains(Flags.Flag.FLAGGED);
            mailboxMailRepository.updateMailIsReadAndIsTop(mailId, isRead, isTop);
        } catch (MessagingException e) {
            mailboxMailErrorLogService.saveMailErrorInfo(mailboxAccount.id(), 0L, mailId, "", e);
            throw exception(POST_OFFICE_GET_MAIL_INFO_ERROR, "MessageId");
        }
    }

    private InternetAddress getSender(MimeMessage mailMessage) throws MessagingException {
        try {
            return (InternetAddress) mailMessage.getSender();
        } catch (MessagingException e) {
                String[] sender = mailMessage.getHeader("Sender");
                if(sender != null && sender.length > 0){
                    return new InternetAddress(sender[0].replaceAll("\\s+", ""));
                }
        }
        return null;
    }

    private Date getReceiveDate(MailboxFolder folder, MimeMessage mailMessage) throws MessagingException {
        if(!folder.folderClass().equals(MailboxFolderClassEnum.RECEIVE.getValue()))
            return null;

        String[] receiveds = mailMessage.getHeader("Received");
        if(receiveds == null)
            return mailMessage.getSentDate();
        for(String receive : receiveds){
            Date receiveDate = extractDate(receive);
            if(receiveDate != null)
                return receiveDate;
        }

        return null;
    }

    private static Date extractDate(String input) {
        // 定义正则表达式匹配日期和时间
        String regex = "\\b[A-Za-z]{3},\\s+\\d{1,2}\\s+[A-Za-z]{3}\\s+\\d{4}\\s+\\d{2}:\\d{2}:\\d{2}\\s+\\+\\d{4}\\b";

        // 使用 Hutool 的 ReUtil 提取匹配的时间字符串
        String dateString = ReUtil.get(regex, input, 0);

        if (dateString != null && !dateString.isEmpty()) {
            // 使用 Hutool 的 DateUtil 解析时间字符串
            return DateUtil.parse(dateString, "EEE, dd MMM yyyy HH:mm:ss Z", Locale.ENGLISH);
        } else {
            return null;
        }
    }

    /**
     * 创建邮件
     * @param folder 系统邮件文件夹
     * @param message 邮件message
     * @param uid  邮件UID
     */
    private void createMail(MailboxFolder folder, Message message, String uid){
        try {
            // 重新读取 解决Failed to load IMAP envelope的问题
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            message.writeTo(bos);
            bos.close();
            SharedByteArrayInputStream bis = new SharedByteArrayInputStream(bos.toByteArray());
            MimeMessage mailMessage = (MimeMessage) receiveProtocol.createMessage(bis);
            bis.close();


            String messageId = getMailMessageId(mailMessage);
            String senderName = "";
            String senderAddress = "";

            // 根据References 判断是否是回复营销邮件
            String[] referencesMessageIds = mailMessage.getHeader("References");
            if(referencesMessageIds != null){
                for(String referencesMessageId : referencesMessageIds){
                    batchSendMailService.handleRelyInfo(referencesMessageId);
                }
            }

            // 获取邮件信息
            InternetAddress messageSenderAddress = getSender(mailMessage);
            if (messageSenderAddress != null) {
                senderName = messageSenderAddress.getPersonal();
                senderAddress = messageSenderAddress.getAddress();
            }

            String subject = mailMessage.getSubject() == null ? "" : mailMessage.getSubject(); // 主题
            List<Address[]> receivers = getReceivers(mailMessage);
            Address[] froms = mailMessage.getFrom(); // 发件人
            int size = mailMessage.getSize();

            LocalDateTime sendTime =  DateUtil.toLocalDateTime(mailMessage.getSentDate()); // 发送日期
            LocalDateTime receiveTime = DateUtil.toLocalDateTime(getReceiveDate(folder, mailMessage)); // 接收日期
            boolean isRead = message.getFlags().contains(Flags.Flag.SEEN);
            boolean isTop = message.getFlags().contains(Flags.Flag.FLAGGED);

            Enumeration<Header> headers = mailMessage.getAllHeaders();
            boolean tempHasAttaches = false;
            while (headers.hasMoreElements()) {
                Header header = headers.nextElement();
                // 检查 X-Has-Attach 是否存在
                if (header.getName().equalsIgnoreCase("X-Has-Attach") && header.getValue().equals("yes")) {
                    tempHasAttaches = true;
                    break;
                }
                // 回复邮件 根据messageId判断是否是营销邮件的回复
            }
            boolean isAttachment = tempHasAttaches;
            
            String finalSenderName = getAddressName(senderAddress, senderName);
            String finalSenderAddress = senderAddress;

            List<MailboxMailFrom> mailFroms = new ArrayList<>();
            if(froms != null){
                for(Address from : froms){
                    InternetAddress internetFrom = (InternetAddress) from;
                    mailFroms.add(MailboxMailFromDraft.$.produce(draft ->
                            draft.setAddress(internetFrom.getAddress())
                                    .setName(getAddressName(internetFrom.getAddress(), internetFrom.getPersonal()))
                            )
                    );
                }
            }
            List<MailboxMailReceiver> mailReceivers = new ArrayList<>();
            for(Address[] addresses : receivers){
                if(addresses == null)
                    continue;
                for(Address to : addresses){
                    InternetAddress internetTo = (InternetAddress) to;
                    mailReceivers.add(MailboxMailReceiverDraft.$.produce(draft ->
                            draft.setAddress(internetTo.getAddress())
                                    .setName(getAddressName(internetTo.getAddress(), internetTo.getPersonal()))
                                    .setType(receivers.indexOf(addresses))
                            )
                    );
                }
            }

            Integer mailType = calcMailType(folder);

            Integer mailStatus = calcMailStatus(folder);

            MailboxMail mail = MailboxMailDraft.$.produce(draft ->
                            draft.setAccountId(mailboxAccount.id()).setCalendar("").setSubject(subject)
                            .setFolderId(folder.id()).setSenderName(finalSenderName) .setSenderAddress(finalSenderAddress)
                            .setSendTime(sendTime).setReceiveTime(receiveTime).setFroms(mailFroms).setIsRead(isRead)
                            .setSize((long) size).setMessageId(messageId).setMailType(mailType).setStatus(mailStatus).setIsAttachment(isAttachment)
                            .setIsTop(isTop).setUid(uid)
                            .setContent(
                                    MailboxMailContentDraft.$.produce(contentDraft -> contentDraft.setContent("").setSearchContent(""))
                            ).setAllReceivers(mailReceivers).setReceiverCount(mailReceivers.size())
            );
            mail = mailboxMailRepository.insert(mail);
            if(mailboxAccount.mailboxProtocolType().equals(MailboxProtocolEnum.POP.getValue())){
                Optional<MailboxMail> optionMailInfo = mailboxMailRepository.getMailInfoById(mail.id());
                if(optionMailInfo.isEmpty()) return;
                String content = getMailContentByMessage(mail.id(), mailMessage);
                String searchContent = getMailSearchContent(optionMailInfo.get(), content);
                List<MailboxMailResource> resources = mailboxMailResourceRepository.findByMailIdAndResourceType(mail.id(), MailboxMailResourceTypeEnum.ATTACHMENT.getValue());
                mailboxMailRepository.updateMailContent(mail.id(), content, searchContent, !resources.isEmpty());
            }
        } catch (MessagingException | IOException e) {
            mailboxMailErrorLogService.saveMailErrorInfo(mailboxAccount.id(), folder.id(), 0L, uid, e);
            throw exception(POST_OFFICE_RECEIVE_MAIL_ERROR);
        }
    }

    private Integer calcMailType(MailboxFolder folder){
        Integer mailType = MailboxMailTypeEnum.RECEIVE.getValue();
        if(folder.folderClass().equals(MailboxFolderClassEnum.SEND.getValue()))
            mailType = MailboxMailTypeEnum.SEND.getValue();
        if(folder.folderClass().equals(MailboxFolderClassEnum.DRAFT.getValue()))
            mailType = MailboxMailTypeEnum.DRAFT.getValue();
        return mailType;
    }

    private Integer calcMailStatus(MailboxFolder folder){
        Integer mailStatus = MailboxMailStatusEnum.RECEIVED.getValue();
        if(folder.folderClass().equals(MailboxFolderClassEnum.SEND.getValue()))
            mailStatus = MailboxMailStatusEnum.SEND.getValue();
        if(folder.folderClass().equals(MailboxFolderClassEnum.JUNK.getValue()))
            mailStatus = MailboxMailStatusEnum.JUNK.getValue();
        if(folder.folderClass().equals(MailboxFolderClassEnum.DRAFT.getValue()))
            mailStatus = MailboxMailStatusEnum.DRAFT.getValue();
        if(folder.folderClass().equals(MailboxFolderClassEnum.DELETED.getValue()))
            mailStatus = MailboxMailStatusEnum.DELETED.getValue();
        return mailStatus;
    }

    /**
     * 下载一个邮件的邮件头
     * @param folder 系统邮箱文件夹
     * @param message 邮件message
     * @param uid 邮件UID
     * @return true 不存在，下载邮件头 false 已经存在，更新邮件标记
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean downloadOneMailHeader(MailboxFolder folder, Message message, String uid){
        boolean isCreate = false;
        try{
            // todo uid可能会重复 是发送邮件有问题导致的 sendmail可能有问题 还需要进一步测试
            Optional<Long> optionalExistsMail = mailboxMailRepository.findFirstByFolderIdAndUid(folder.id(), uid);
            if(optionalExistsMail.isPresent()){
                updateMailFlag(optionalExistsMail.get(), message);
            }else{
                createMail(folder, message, String.valueOf(uid));
                isCreate = true;
            }
        }catch (Exception e){
            mailboxMailErrorLogService.saveMailErrorInfo(mailboxAccount.id(), folder.id(), 0L, uid, e);
        }
        return isCreate;
    }

    /**
     * 获取邮件的收件人、抄送人、密送人
     * @param message 邮件message
     * @return 邮件的收件人、抄送人、密送人
     */
    @NotNull
    private List<Address[]> getReceivers(Message message) throws MessagingException {
        List<Address[]> receivers = new ArrayList<>();
        receivers.add(message.getRecipients(Message.RecipientType.TO)); // 收件人
        receivers.add(message.getRecipients(Message.RecipientType.CC)); // 抄送
        receivers.add(message.getRecipients(Message.RecipientType.BCC)); // 密送
        return receivers;
    }


    /**
     * 获取邮件的MessageID
     * @param message 邮件message
     * @return MessageID
     */
    private String getMailMessageId(Message message) throws MessagingException {
        String messageId;

        String[] messageIds = message.getHeader("Message-ID");
        messageId = messageIds == null ? "" : messageIds[0];

        return messageId;
    }

    /**
     * 获取邮件地址的邮件人姓名
     * @param address 邮件地址
     * @param personal 邮件的地址人
     * @return 邮件人姓名
     */
    private String getAddressName(String address, String personal){
        if (personal != null)
            return personal;
        if (address  == null || !address.contains("@"))
            return "";
        else{
            return address.substring(0, address.indexOf("@"));
        }
    }

    /**
     * 获取邮件正文
     * @param folder 邮件所在文件夹
     * @param mail 邮件
     * @return 邮件正文
     */
    public String getMailContent(MailboxFolder folder, MailboxMail mail){
        String content;
        Folder postOfficeFolder = receiveProtocol.getFolderByName(folder.postOfficeName());
        receiveProtocol.openFolder(postOfficeFolder, Folder.READ_ONLY);
        String[] uids = {mail.uid()};
        log.info("开始获取 uid " + mail.uid());
        Message[] messages = receiveProtocol.getMessagesByUid(postOfficeFolder, uids);
        content = getMailContentByMessage(mail.id(), messages[0]);
        log.info("结束获取");
        receiveProtocol.closeFolder(postOfficeFolder, false);
        return content;
    }

    /**
     * 根据Message获取邮件正文
     * @param mailId 邮件ID
     * @param message 邮件message
     * @return 邮件正文
     */
    private String getMailContentByMessage(Long mailId, Message message){
        String mailContent = "";
        try {
            if (message instanceof MimeMessage mimeMessage) {
                // 获取邮件内容
                Object content;
                content = mimeMessage.getContent();

                // 处理不同的内容类型
                if (content instanceof String) {
                    // 纯文本邮件
                    mailContent = content.toString();
                } else if (content instanceof MimeMultipart multipart) {
                    // 多部分邮件（包含附件或不同格式的内容）
                    String contentType = multipart.getContentType().toLowerCase(Locale.ROOT);
                    if(contentType.contains("multipart/related") || contentType.contains("multipart/mixed")){
                        mailContent = processMultipart(mailId, multipart);
                    }else if(contentType.contains("multipart/alternative")){
                        mailContent = processMultiAlternative(mailId, multipart);
                    }else{
                        log.info("this is tmpGetMailContent unknown type " + contentType);
                    }
                    mailContent = replaceInlineResourceUrl(mailId, mailContent);
                }

            } else {
                if(message != null && message.getContent() != null )
                mailContent = message.getContent().toString();
            }
        }catch (Exception e) {
            mailboxMailErrorLogService.saveMailErrorInfo(mailboxAccount.id(), 0L, mailId, "", e);
            throw exception(POST_OFFICE_RECEIVE_MAIL_ERROR);
        }
        return mailContent;
    }

    /**
     * 替换内联类型的资源的URL
     * @param mailId 邮件ID
     * @param mailContent 邮件正文
     * @return 替换后的邮件正文
     */
    private String replaceInlineResourceUrl(Long mailId, String mailContent){
        List<MailboxMailResource> resourceList = mailboxMailResourceRepository.findByMailIdAndResourceType(mailId, MailboxMailResourceTypeEnum.INLINE.getValue());
        if(resourceList.size() > 0){
            for(MailboxMailResource resource : resourceList){
                String sourceUrl = "cid:" + resource.fileName();
                int index = mailContent.indexOf(sourceUrl);
                if(index > 0){
                    mailContent = mailContent.replaceAll(sourceUrl, resource.urlName());
                }else{
                    log.info(" mailId: " + mailId + " 资源名：" + sourceUrl + " 在正文中不存在");
                    throw exception(POST_OFFICE_RECEIVE_MAIL_ERROR);
                }
            }
        }
        return mailContent;
    }

    /**
     * 报错邮件资源
     * @param mailId 邮件ID
     * @param bodyPart 资源的邮件体
     * @param defaultResourceType 默认的邮件资源类型
     */
    private void saveMailResource(Long mailId, BodyPart bodyPart, int defaultResourceType) throws MessagingException, IOException {

        int resourceType = defaultResourceType;
        String[] dispositions = bodyPart.getHeader("Content-Disposition");
        if(dispositions != null){
            if(dispositions.length != 1){
                log.info(" mailId: " + mailId + " fileName:" + bodyPart.getFileName() + " Content-Disposition 不为1");
                throw exception(POST_OFFICE_RECEIVE_MAIL_ERROR);
            }
            if(dispositions[0].contains("attachment")){
                resourceType = MailboxMailResourceTypeEnum.ATTACHMENT.getValue();
            }else if(dispositions[0].contains("inline")){
                resourceType = MailboxMailResourceTypeEnum.INLINE.getValue();
            }else{
                log.info(" mailId: " + mailId + " fileName:" + bodyPart.getFileName() + " Content-Disposition：" + dispositions[0] + "  不是attachment和inline");
                throw exception(POST_OFFICE_RECEIVE_MAIL_ERROR);
            }
        }

        String resourceName = getResourceName(resourceType, bodyPart);
        InputStream inputStream = bodyPart.getInputStream();
        byte[] content = IOUtils.toByteArray(inputStream);
        String fileUrl = fileService.createFile(resourceName, "", content);
        Optional<MailboxMailResource> optionalResource = mailboxMailResourceRepository.findFirstByMailIdAndFileName(mailId, resourceName);
        if(optionalResource.isEmpty()){
            int finalResourceType = resourceType;
            MailboxMailResource attachment = MailboxMailResourceDraft.$.produce(draft ->
                    draft.setMailId(mailId).setFileName(resourceName).setUrlName(fileUrl)
                            .setResourceType(finalResourceType).setSize(content.length)
            );
            mailboxMailResourceRepository.insert(attachment);
        }

    }

    /**
     * 获取邮件资源的资源名称
     * @param resourceType 资源类型
     * @param bodyPart 资源的邮件体
     * @return 资源名称
     */
    private String getResourceName(int resourceType, BodyPart bodyPart)throws MessagingException, IOException{
        if(Objects.equals(resourceType, MailboxMailResourceTypeEnum.ATTACHMENT.getValue())){
            return MimeUtility.decodeText(bodyPart.getFileName().trim());
        }else{
            String resourceName;
            String contentId = "";
            String[] contentIds = bodyPart.getHeader("Content-ID");
            // 去除前后的<>符号
            if (contentIds != null && contentIds.length == 1 && contentIds[0].length() > 0) {
                contentId = contentIds[0];
                if(contentId.charAt(0) == '<')
                    contentId = contentId.substring(1);
                if(contentId.charAt(contentId.length() - 1) == '>')
                    contentId = contentId.substring(0,  contentId.length() - 1);
            }
            if (!contentId.isEmpty()) {
                resourceName = contentId;
            }else{
                resourceName = bodyPart.getFileName();
            }
            return resourceName;
        }
    }

    /**
     * 处理日程类型的邮件体
     * @param mailId 邮件ID
     * @param bodyPart 日程类型的邮件体
     */
    private void processCalendarType(Long mailId, BodyPart bodyPart)  throws MessagingException, IOException{
        mailboxMailRepository.updateMailCalendar(mailId,  new String(IOUtils.toByteArray(bodyPart.getInputStream())));
    }

    /**
     * 处理组合类型的邮件体
     * @param mailId 邮件ID
     * @param multipart 组合类型的邮件体
     * @return 邮件体内容
     */
    private String processMultipart(Long mailId, Multipart multipart) throws MessagingException, IOException {
        StringBuilder mailContent = new StringBuilder();
        for (int i = 0; i < multipart.getCount(); i++) {
            BodyPart bodyPart = multipart.getBodyPart(i);
            String contentType = bodyPart.getContentType().toLowerCase(Locale.ROOT);
            if (contentType.contains("text/plain") || contentType.contains(("text/html")) || contentType.contains("message/rfc822")) {
                mailContent.append(bodyPart.getContent().toString());
            } else if (contentType.contains("text/csv") || contentType.contains("application/")) {
                saveMailResource(mailId, bodyPart, MailboxMailResourceTypeEnum.ATTACHMENT.getValue());
            } else if (contentType.contains(("text/calendar"))) {
                processCalendarType(mailId, bodyPart);
            } else if (contentType.contains("multipart/alternative")) {
                mailContent.append(processMultiAlternative(mailId, (Multipart) bodyPart.getContent()));
            } else if(contentType.contains("image/")) {
                saveMailResource(mailId, bodyPart, MailboxMailResourceTypeEnum.INLINE.getValue());
            } else if(contentType.contains("message/delivery-status")) {
                log.info(" mailId: " + mailId + " is message/delivery-status");
            } else if (bodyPart.getContent() instanceof Multipart) {
                // 如果该部分也是Multipart，则递归处理
                mailContent.append(processMultipart(mailId, (Multipart)bodyPart.getContent()));
            } else {
                log.info(" mailId: " + mailId + "未知的类型（可能是附件） 类型为：" + contentType);
                saveMailResource(mailId, bodyPart, MailboxMailResourceTypeEnum.INLINE.getValue());
            }
        }
        return mailContent.toString();
    }

    /**
     * 处理可替代类型的邮件体
     * @param mailId 邮件ID
     * @param multipart 可替代类型的邮件体
     * @return 邮件体内容
     */
    private String processMultiAlternative(Long mailId, Multipart multipart) throws MessagingException, IOException{
        String textString = "";
        String htmlString = "";
        for (int i = 0; i < multipart.getCount(); i++) {
            BodyPart bodyPart = multipart.getBodyPart(i);
            String contentType = bodyPart.getContentType().toLowerCase(Locale.ROOT);
            if (contentType.contains("text/html")) {
                htmlString = bodyPart.getContent().toString();
            }else if(contentType.contains("text/plain")){
                textString = bodyPart.getContent().toString();
            } else if (contentType.contains("text/csv") || contentType.contains("application/")) {
            saveMailResource(mailId, bodyPart, MailboxMailResourceTypeEnum.ATTACHMENT.getValue());
            } else if (contentType.contains(("text/calendar"))) {
                processCalendarType(mailId, bodyPart);
            }else if(contentType.contains("image/")) {
                saveMailResource(mailId, bodyPart, MailboxMailResourceTypeEnum.INLINE.getValue());
            } else if(contentType.contains("message/delivery-status")) {
                log.info(" mailId: " + mailId + " is message/delivery-status");
            } else{
                log.info("mailId:" + mailId +" processMultiAlternative unknown type " + bodyPart.getContentType());
            }
        }
        if(htmlString.isEmpty())
            return textString;
        else
            return htmlString;
    }

    private MimeMultipart createMailContent(MailboxMail mail) throws Exception {
        // 创建邮件内容的多部分
        String subType = mail.resources().stream().anyMatch(resource -> resource.resourceType().equals(MailboxMailResourceTypeEnum.ATTACHMENT.getValue()))
                ?  "mixed" : "related";

        MimeMultipart multipart = new MimeMultipart(subType);


        String htmlContent = Objects.requireNonNull(mail.content()).content();

        for(MailboxMailResource resource : mail.resources()){
            MimeBodyPart bodyPart = new MimeBodyPart();
            if(!resource.urlName().contains("/admin-api/infra/file/"))
                continue;
            String strConfigId = StrUtil.subBefore(StrUtil.subAfter(resource.urlName(), "/admin-api/infra/file/", false), "/get/", false);
            String path = StrUtil.subAfter(resource.urlName(), "/get/", false);
            byte[] content = fileService.getFileContent(Long.parseLong(strConfigId), path);
            String type = FileTypeUtils.getMineType(content, resource.fileName());
            DataSource dataSource = new ByteArrayDataSource(content, type); // 设置附件的MIME类型
            bodyPart.setDataHandler(new DataHandler(dataSource));
            if(resource.resourceType().equals(MailboxMailResourceTypeEnum.ATTACHMENT.getValue())){
                bodyPart.setFileName(resource.fileName()); // 设置附件的文件名
            }else{
                String cidName = resource.urlName().substring(resource.urlName().lastIndexOf("/") + 1);
                bodyPart.setContentID("<" + cidName +">"); // 设置图片的 Content-ID
                bodyPart.setDisposition(MimeBodyPart.INLINE); // 设置为内联图片
                htmlContent = htmlContent.replace(resource.urlName(), "cid:" + cidName);
            }
            multipart.addBodyPart(bodyPart);
        }

        // 创建邮件的正文部分（HTML格式）
        MimeBodyPart textPart = new MimeBodyPart();
        textPart.setContent(htmlContent, "text/html; charset=UTF-8");
        textPart.setHeader("Content-Transfer-Encoding", "quoted-printable");
        // 添加正文部分到邮件中
        multipart.addBodyPart(textPart);
        return multipart;
    }

    private Message createMailMessage(MailboxMail mail, String customId) throws Exception {

        Message newMessage = receiveProtocol.createMessage();

        newMessage.setSubject(mail.subject());

        newMessage.setHeader("X-XI-UID", customId);

        if(mail.resources().stream().anyMatch(resource -> resource.resourceType().equals(MailboxMailResourceTypeEnum.ATTACHMENT.getValue()))){
            newMessage.setHeader("X-Has-Attach", "yes");
        }else{
            newMessage.setHeader("X-Has-Attach", "no");
        }

        if(mail.froms().size() > 0){
            newMessage.setFrom(new InternetAddress(mail.froms().get(0).address(), mail.froms().get(0).name()));
        }
        if(mail.receivers().size() > 0){
            List<InternetAddress> toRecipients = new ArrayList<>();
            for(MailboxMailReceiver receiver : mail.receivers()){
                toRecipients.add(new InternetAddress(receiver.address(), receiver.name()));
            }
            newMessage.setRecipients(Message.RecipientType.TO, toRecipients.toArray(InternetAddress[]::new));
        }

        if(mail.carbonReceivers().size() > 0){
            List<InternetAddress> toRecipients = new ArrayList<>();
            for(MailboxMailReceiver receiver : mail.carbonReceivers()){
                toRecipients.add(new InternetAddress(receiver.address(), receiver.name()));
            }
            newMessage.setRecipients(Message.RecipientType.CC, toRecipients.toArray(InternetAddress[]::new));
        }

        if(mail.blindReceivers().size() > 0){
            List<InternetAddress> toRecipients = new ArrayList<>();
            for(MailboxMailReceiver receiver : mail.blindReceivers()){
                toRecipients.add(new InternetAddress(receiver.address(), receiver.name()));
            }
            newMessage.setRecipients(Message.RecipientType.BCC, toRecipients.toArray(InternetAddress[]::new));
        }
        MimeMultipart multipart = createMailContent(mail);
        newMessage.setContent(multipart);
        return newMessage;
    }

    public void saveMail(Long mailId) throws Exception {

        MailboxMail mail = mailboxMailRepository.getMailDetailById(mailId).orElse(null);
        if(mail == null)
            return;
        MailboxFolder mailboxDraftFolder = mailboxFolderRepository.findNullable(mail.folderId());

        String customId = "xit" + System.currentTimeMillis() + "t" + mail.id();

        Message newMessage = createMailMessage(mail, customId);

        Folder postOfficeSaveFolder = getPostOfficeFolder(mailboxDraftFolder);
        receiveProtocol.openFolder(postOfficeSaveFolder, Folder.READ_WRITE);
        String newUid = receiveProtocol.getNextUid(postOfficeSaveFolder);
        postOfficeSaveFolder.appendMessages(new Message[]{newMessage});

        String[] messageIds = newMessage.getHeader("Message-ID");
        String messageId = "";
        if (messageIds != null && messageIds[0] != null) {
            messageId = messageIds[0];
        }
        int size = getMessageSize(newMessage);

        receiveProtocol.closeFolder(postOfficeSaveFolder, true);

        // 更新邮件的MessageId size uid
        mailboxMailRepository.updateMailInfo(mailId, newUid, size, messageId, mail.sendTime(), mail.receiveTime());

        mailboxFolderRepository.updateCount(mailboxDraftFolder.id(), mailboxDraftFolder.mailCount() + 1, mailboxDraftFolder.readMailCount() + 1, mailboxDraftFolder.topMailCount());

        updateNewMailInfo(mail.id(), postOfficeSaveFolder, customId);

    }

    public void sendMail(Long mailId) {
        try{
            MailboxMail mail = mailboxMailRepository.getMailDetailById(mailId).orElse(null);
            if(mail == null)
                return;
            if(!Objects.equals(mail.uid(), "")){
                List<MailboxFolder> folders = mailboxFolderRepository.findByAccountIdAndFolderTypeAndFolderClass(mailboxAccount.id(), MailboxFolderTypeEnum.INTERNAL.getValue(), MailboxFolderClassEnum.DRAFT.getValue());
                if(folders.size() == 0){
                    throw exception(MAILBOX_FOLDER_CLASS_NOT_EXIST,   "草稿箱");
                }
                MailboxFolder draftFolder = folders.get(0);
                Folder postOfficeDraftFolder = getPostOfficeFolder(draftFolder);
                receiveProtocol.openFolder(postOfficeDraftFolder, Folder.READ_WRITE);
                String[] uniqueIds = {mail.uid()};
                Message[] messages = receiveProtocol.getMessagesByUid(postOfficeDraftFolder, uniqueIds);
                receiveProtocol.deleteMessages(postOfficeDraftFolder, messages);
                receiveProtocol.closeFolder(postOfficeDraftFolder, true);

            }

            // 根据邮箱账号查找发件箱
            List<MailboxFolder> folders = mailboxFolderRepository.findByAccountIdAndFolderTypeAndFolderClass(mailboxAccount.id(),
                    MailboxFolderTypeEnum.INTERNAL.getValue(), MailboxFolderClassEnum.SEND.getValue());

            if(folders.size() == 0){
                throw exception(MAILBOX_FOLDER_CLASS_NOT_EXIST, "已发送邮件" );
            }

            MailboxFolder mailboxSendFolder = folders.get(0);

            String customId = "xit" + System.currentTimeMillis() + "t" + mail.id();

            Message newMessage = createMailMessage(mail, customId);

            Folder postOfficeSendFolder = getPostOfficeFolder(mailboxSendFolder);
            receiveProtocol.openFolder(postOfficeSendFolder, Folder.READ_WRITE);
            String newUid = receiveProtocol.getNextUid(postOfficeSendFolder);


            Transport transport = smtpProtocol.getSmtpProtocol(mailboxAccount);
            transport.sendMessage(newMessage, newMessage.getAllRecipients());
            String[] messageIds = newMessage.getHeader("Message-ID");
            String messageId = "";
            if (messageIds != null && messageIds[0] != null) {
                messageId = messageIds[0];
            }
            int size = getMessageSize(newMessage);
            receiveProtocol.closeFolder(postOfficeSendFolder, false);

            // 更新邮件的MessageId size uid
            String finalMessageId = messageId;
            MailboxMail updateMail = MailboxMailDraft.$.produce(
                    draft -> draft.setId(mailId).setUid(newUid).setSize((long) size).setMessageId(finalMessageId).setSendTime(LocalDateTime.now())
                            .setReceiveTime(LocalDateTime.now()).setFolderId(mailboxSendFolder.id()).setStatus(MailboxMailStatusEnum.SEND.getValue())
                            .setMailType(MailboxMailTypeEnum.SEND.getValue())
            );
            mailboxMailRepository.update(updateMail);
//            mailboxMailRepository.updateMailInfo(mailId, newUid, size, messageId, mail.sendTime(), mail.receiveTime(), mailboxSendFolder.id(), MailboxMailStatusEnum.SEND.getValue());

            // 更新文件夹的总邮件数量、已读数量
            mailboxFolderRepository.updateCount(mailboxSendFolder.id(), mailboxSendFolder.mailCount() + 1, mailboxSendFolder.readMailCount() + 1, mailboxSendFolder.topMailCount());

            updateNewMailInfo(mail.id(), postOfficeSendFolder, customId);
        } catch (Exception e) {
            mailboxMailErrorLogService.saveMailErrorInfo(mailboxAccount.id(), 0L, mailId, "", e);
            throw exception(POST_OFFICE_SEND_MESSAGE_ERROR, e.getMessage());
        }
    }

    private static int getMessageSize(Message message) throws MessagingException, IOException {
        // 将 MimeMessage 写入 ByteArrayOutputStream
        try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
            message.writeTo(byteArrayOutputStream);  // 将邮件内容写入输出流
            return byteArrayOutputStream.size();     // 返回邮件的字节大小
        }
    }

    private void updateNewMailInfo(Long mailId, Folder postOfficeSendFolder, String customId){

        if(mailboxAccount.mailboxProtocolType().equals(MailboxProtocolEnum.POP.getValue()))
            return;

        // 创建一个定时任务调度器
        ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);

        Runnable task = () -> {
            try {
                receiveProtocol.openFolder(postOfficeSendFolder, Folder.READ_ONLY);
                Message[] messages = postOfficeSendFolder.getMessages();

                boolean isMatch = false;
                for(int index = messages.length - 1; index >= 0; index--){
                    Enumeration<Header> headers = messages[index].getAllHeaders();

                    // 遍历并输出所有头部字段
                    while (headers.hasMoreElements()) {
                        Header header = headers.nextElement();
                        // 检查 X-XI-UID 是否存在
                        if (header.getName().equalsIgnoreCase("X-XI-UID") && header.getValue().equals(customId)) {
                            isMatch = true;
                            break;
                        }
                    }
                    if(isMatch){
                        int size = messages[index].getSize();
                        String messageId = getMailMessageId(messages[index]);
                        IMAPFolder imapFolder = (IMAPFolder)postOfficeSendFolder;
                        long uid = imapFolder.getUID(messages[index]);
                        LocalDateTime sendTime =  DateUtil.toLocalDateTime(messages[index].getSentDate()); // 发送日期
                        LocalDateTime receiveTime = DateUtil.toLocalDateTime(messages[index].getReceivedDate()); // 接收日期
                        mailboxMailRepository.updateMailInfo(mailId, String.valueOf(uid), size, messageId, sendTime, receiveTime);
                        break;
                    }
                    if(messages.length - index > 5)
                        break;
                }
                receiveProtocol.closeFolder(postOfficeSendFolder, false);
            } catch (MessagingException e) {
                mailboxMailErrorLogService.saveMailErrorInfo(mailboxAccount.id(), 0L, mailId, "", e);
                throw exception(POST_OFFICE_UPDATE_NEW_MAIL_ERROR, "MessageId");
            }

        };

        // 延时 2 秒后执行任务
        scheduler.schedule(task, 2, TimeUnit.SECONDS);

        // 关闭调度器
        scheduler.shutdown();
    }

    public String saveMailAsFile(MailboxMail mail) throws MessagingException, IOException {
        MailboxFolder folder = mailboxFolderRepository.findNullable(mail.folderId());
        Folder postOfficeFolder = getPostOfficeFolder(folder);
        receiveProtocol.openFolder(postOfficeFolder, Folder.READ_ONLY);
        String[] uniqueIds = {mail.uid()};
        Message[] messages = receiveProtocol.getMessagesByUid(postOfficeFolder, uniqueIds);
        if(messages == null || messages[0] == null){
            receiveProtocol.closeFolder(postOfficeFolder, false);
            return "";
        }
        String fileName = Objects.equals(mail.subject(), "") ? "export.eml" : mail.subject() + ".eml";
        String url;

        url = fileService.createFile(fileName, "", convertMessageToByteArray(messages[0]));


        receiveProtocol.closeFolder(postOfficeFolder, false);
        return url;

    }

    private static byte[] convertMessageToByteArray(Message message) throws MessagingException, IOException {
        // 使用 ByteArrayOutputStream 来将 MimeMessage 写入字节数组
        try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
            message.writeTo(byteArrayOutputStream);
            return byteArrayOutputStream.toByteArray();
        }
    }

}
